﻿// ----------------------------------------------------------------------------------
// <copyright file="PluggableForAllValuesOfEnumExceptAttribute.cs" company="Christopher Hines">
// Copyright (c) 2012 All Right Reserved
// </copyright>
// <author>Chris Hines</author>
// <date>2012-03-26</date>
// <summary>
//     An attribute for decorating a class as pluggble for all values of an Enum type except specific values
// </summary>
// ----------------------------------------------------------------------------------

namespace Copperfield
{
    using System;
    using System.Collections.Generic;
    using System.Linq;

    /// <summary>
    /// An attribute for decorating a class as pluggble for all values of an Enum type except specific values
    /// </summary>
    [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false)]
    public sealed class PluggableForAllValuesOfEnumExceptAttribute : ContextFilterAttribute
    {
        /// <summary>
        /// The enum values.
        /// </summary>
        private readonly IEnumerable<object> enumValues;

        /// <summary>
        /// Initializes a new instance of the <see cref="PluggableForAllValuesOfEnumExceptAttribute"/> class.
        /// </summary>
        /// <param name="enumValues">
        /// The enum values.
        /// </param>
        public PluggableForAllValuesOfEnumExceptAttribute(params object[] enumValues)
            : base(enumValues[0].GetType(), enumValues, true)
        {
            this.enumValues = enumValues;
            
            var firstValue = enumValues[0];

            if (enumValues.Where(x => !x.Equals(firstValue)).Any(x => x.GetType() != firstValue.GetType()))
            {
                throw new ArgumentException("All params values must be of the same type", "enumValues");
            }

            if (!firstValue.GetType().IsEnum)
            {
                throw new ArgumentException("The filter type must be a type of Enum", "enumValues");
            }
        }

        /// <summary>
        /// Gets the enum values.
        /// </summary>
        public IEnumerable<object> EnumValues
        {
            get
            {
                return this.enumValues;
            }
        }
    }
}
